using System;
using System.Collections;
using System.ComponentModel;
using System.Web;
using System.Web.UI;

namespace MyControls.DataSources.CompositeHierarchicalDataSource {
    /// <summary>
    /// A collection of <see cref="Relation"/>s. This collection can maintain state in the ViewState.
    /// </summary>
    public class RelationCollection : StateManagedCollection {
        private static readonly Type[] knownTypes = new Type[] { typeof(Relation) };
        private CompositeHierarchicalDataSource _owner;

        internal RelationCollection() {
        }

        /// <summary>
        /// Constructs a collection with the specified owner.
        /// </summary>
        /// <param name="owner">The <see cref="CompositeHierarchicalDataSource"/> that owns this collection.</param>
        internal RelationCollection(CompositeHierarchicalDataSource owner)
            : this() {
            _owner = owner;
        }

        /// <summary>
        /// The <see cref="CompositeHierarchicalDataSource"/> that owns this collection.
        /// </summary>
        /// <value></value>
        internal CompositeHierarchicalDataSource Owner {
            get {
                return _owner;
            }
        }

        /// <summary>
        /// Indexed and strongly-typed access to the elements of the collection.
        /// </summary>
        /// <param name="i">The index of the element.</param>
        /// <returns>The relation at that index.</returns>
        public Relation this[int i] {
            get {
                return (Relation)((IList)this)[i];
            }
            set {
                ((IList)this)[i] = value;
            }
        }

        /// <summary>
        /// Adds a relation to the collection.
        /// </summary>
        /// <param name="relation"></param>
        /// <returns></returns>
        public int Add(Relation relation) {
            relation.SetOwner(_owner);
            return ((IList)this).Add(relation);
        }

        /// <summary>
        /// Determines if a <see cref="Relation"/> is in the collection.
        /// </summary>
        /// <param name="relation">The relation to find.</param>
        /// <returns>true if the relation is in the collection.</returns>
        public bool Contains(Relation relation) {
            return ((IList)this).Contains(relation);
        }

        /// <summary>
        /// Copies the collection to a <see cref="Relation"/> array.
        /// </summary>
        /// <param name="relationArray">The array to copy the collection to.</param>
        /// <param name="index">The index at which copying begins.</param>
        public void CopyTo(Relation[] relationArray, int index) {
            base.CopyTo(relationArray, index);
        }

        /// <summary>
        /// The index of the provided <see cref="Relation"/>.
        /// </summary>
        /// <param name="relation">The <see cref="Relation"/> for which we want the index.</param>
        /// <returns>The index of the <see cref="Relation"/> if it is in the colleciton, -1 otherwise.</returns>
        public int IndexOf(Relation relation) {
            return ((IList)this).IndexOf(relation);
        }

        /// <summary>
        /// Inserts a <see cref="Relation"/> into the collection at the specified index.
        /// </summary>
        /// <param name="index">The index where to insert.</param>
        /// <param name="relation">The <see cref="Relation"/> to insert.</param>
        public void Insert(int index, Relation relation) {
            relation.SetOwner(_owner);
            ((IList)this).Insert(index, relation);
        }

        protected override object CreateKnownType(int index) {
            return new Relation(_owner);
        }

        protected override Type[] GetKnownTypes() {
            return knownTypes;
        }

        /// <summary>
        /// Removes a <see cref="Relation"/> from the collection.
        /// </summary>
        /// <param name="relation">The <see cref="Relation"/> to remove.</param>
        public void Remove(Relation relation) {
            ((IList)this).Remove(relation);
        }

        /// <summary>
        /// Removes a <see cref="Relation"/> from the collection.
        /// </summary>
        /// <param name="index">The index of the <see cref="Relation"/> to remove.</param>
        public void RemoveAt(int index) {
            ((IList)this).RemoveAt(index);
        }

        protected override void SetDirtyObject(object o) {
            if (o is Relation) {
                ((Relation)o).SetDirty();
            }
        }
    }
}

